local core = require("core")

local plugin_name = "whitefilter"
local log = core.log.new(plugin_name .. ": ")
local app_config = require("conf.config").get(plugin_name)
--local plugin_config = app_config[plugin_name]
local template = require "plugins.common.template"

local redis = require("plugins.common.redis")
local redis_cluster = require("plugins.common.redis_cluster")
--log.error(table.concat())
local util = require "plugins.common.util"
--local new_tab = require("table.new")
local ipmatcher = require("resty.ipmatcher")
local white_filter = ngx.shared.white_filter
local black_filter = ngx.shared.black_filter
--log.error(plugin_config)
local redis_white_cache_timeout = app_config["redis_white_cache_timeout"] or 300
local redis_black_cache_timeout = app_config["redis_black_cache_timeout"] or 120
local status_code = app_config["status_code"]
local msg = app_config["msg"]
local allow_ips
--local allow_ips = new_tab(0,200)
local ngx_re = require "ngx.re"

do
    --for _,ip in ipairs(app_config["allow_ips"] or {}) do
    --    allow_ips[ip] = ""
    --end
    allow_ips = ipmatcher.new(app_config["allow_ips"] or {})
end

local red = nil
local red_prefix = app_config["redis_prefix"] or ""

-- optional 是否可选
local _M = {
    name = plugin_name,
    desc = "white list filter",
    optional = false,
    version = "v1.0"
}

--function _M.do_in_init()
--    --log.notice("do_in_init")
--    -- body
--end

-- 提供给测试框架使用，新增白名单ip
function _M.get_red()
    return red
end

function _M.do_in_init_worker()
    --log.info("do_in_init_worker")
    -- body
    -- 如果redis为单机模式
    local redis_type = app_config["type"]
    if redis_type == "redis" then
        local opts = {
            --ip = config.get("app.redis_ip"),
            ip = app_config["redis_ip"],
            --port = config.get("app.redis_port"),
            port = app_config["redis_port"],
            --password = config.get("app.redis_pass"),
            password = app_config["redis_pass"],
            --db_index = config.get("app.redis_db"),
            db_index = app_config["redis_db"],
            --timeout = config.get("app.redis_timeout"),
            timeout = app_config["redis_timeout"],
            --pool_size = config.get("app.redis_pool_size"),
            pool_size = app_config["redis_pool_size"],
        }
        red = redis:new(opts)
    elseif redis_type == "redis_cluster" then
        local opts = {
            serv_list = {},
            pool_max_idle_time = app_config["pool_max_idle_time"],
            pool_size =  app_config["redis_pool_size"],
            timeout = app_config["redis_timeout"],
            max_redirection = app_config["max_redirection"],
            max_connection_attempts = app_config["max_connection_attempts"],
            pass = app_config["redis_pass"],
            dict_name = app_config["dict_name"]
        }
        for i, conf_item in ipairs(app_config["redis_serv_list"]) do
            local res,err = ngx_re.split(conf_item,":")
            --local host = res[1]
            --local port = res[2]
            --ngx.log(ngx.ERR,host .. port ..  i)
            opts.serv_list[i] = { ip = res[1] ,port = res[2]}
        end
        --ngx.log(ngx.ERR,opts.pool_size)
        red = redis_cluster:new(opts)
    end
end

--function _M.do_in_rewrite()
--    --log.notice("do_in_rewrite")
--    --log.error("do_in_rewrite")
--    -- body
--end

function _M.do_in_access()
    if red == nil then
        return
    end
    --log.error(table.concat(util.get_ip_mode))
    local client_ip = util.get_client_ip(app_config["header_ip_args"]);
    --for _,ip in ipairs(allow_ips) do
    --    if client_ip == ip then
    --        return
    --    end
    --end

    if allow_ips:match(client_ip) then
        return
    end
    --if allow_ips[client_ip] then
    --    --log.error("===",allow_ips[client_ip])
    --    return
    --end
    local redis_key =  red_prefix .. client_ip
    if  black_filter:get(redis_key) then

        --return template:render("common",msg,status_code)
        return template:render(msg,status_code)
    end
    if not white_filter:get(redis_key) then
        log.error("本地白名单和黑名单都未找到！去redis查找: ",client_ip)
        local is_exist,err = red:get(redis_key)
        -- 如果查询redis失败或者超时不再进入限流逻辑
        if err ~= nil then
            log.error(err)
            return
        end
        -- is_exist不存在或者值为1即为黑名单
        if not is_exist or tonumber(is_exist) == 1 then
            --log.error(client_ip)
            black_filter:set(redis_key,"",redis_black_cache_timeout)
            --return template:render("common","access_deny",status_code)
            return template:render(msg,status_code)
        end
        white_filter:set(redis_key,"",redis_white_cache_timeout)

    end

end

--function _M.do_in_content()
--    --log.notice("do_in_content")
--    -- body
--end
--
--function _M.do_in_balancer()
--    --log.notice("do_in_balancer")
--    -- body
--end
--
--function _M.do_in_body_filter()
--    --log.error("do_in_body_filter")
--    -- body
--end
--
--function _M.do_in_log()
--    --log.error("do_in_log")
--    -- body
--end

setmetatable(_M,{
    __tostring = function(self)
        return self.name
    end
})

return _M